home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Die Speccy' 97
/
Die Speccy' 97.iso
/
amiga_system
/
the_aminet
/
util
/
shell
/
csh548src.lha
/
sub.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-04
|
29KB
|
1,507 lines
/*
* SUB.C
*
* (c)1986 Matthew Dillon 9 October 1986
*
* Version 2.07M by Steve Drew 10-Sep-87
* Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
* Version 5.00L by Urban Mueller 17-Feb-91
*
*/
#include "shell.h"
static void del_history( void );
static int dnext( DPTR *dp, char **pname, int *stat);
static char *svfile( char *s1, char *s2, FIB *fib);
static void quicksort( char **av, int n );
void
seterr( int err )
{
static int LastErr;
char buf[32], *val;
int stat=0;
Lastresult=err;
if( LastErr!=err ) {
LastErr=err;
sprintf(buf, "%d", err);
set_var(LEVEL_SET, v_lasterr, buf);
if( val=get_var(LEVEL_SET, v_stat))
stat = atoi(val);
if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
}
}
char *
next_word( char *str )
{
while (*str && ! ISSPACE(*str)) ++str;
while (*str && ISSPACE(*str)) ++str;
return str;
}
/*
* FREE(ptr) --frees without actually freeing, so the data is still good
* immediately after the free.
*/
void
Free( void *ptr )
{
static char *old_ptr;
if (old_ptr) free (old_ptr);
old_ptr = ptr;
}
/*
* Add new string to history (H_head, H_tail, H_len,
* S_histlen
*/
void
add_history( char *str )
{
HIST *hist;
char *get;
for( get=str; *get; get++ )
if( (*get&127)<' ')
*get=' ';
if (H_head != NULL && !strcmp(H_head->line, str))
return;
while (H_len > S_histlen)
del_history();
hist = (HIST *)salloc (sizeof(HIST));
if (H_head == NULL) {
H_head = H_tail = hist;
hist->next = NULL;
} else {
hist->next = H_head;
H_head->prev = hist;
H_head = hist;
}
hist->prev = NULL;
hist->line = salloc (strlen(str) + 1);
strcpy (hist->line, str);
++H_len;
H_num= H_tail_base+ H_len;
}
static void
del_history()
{
if (H_tail) {
--H_len;
++H_tail_base;
free (H_tail->line);
if (H_tail->prev) {
H_tail = H_tail->prev;
free (H_tail->next);
H_tail->next = NULL;
} else {
free (H_tail);
H_tail = H_head = NULL;
}
}
}
char *
get_history( char *ptr )
{
int hnum=find_history( ptr+1, 1 );
HIST *hist;
for( hist=H_head; hist && hnum--; hist=hist->next) ;
if( !hist ) {
fprintf(stderr,"History failed\n");
return "";
}
fprintf(stderr, "%s\n", hist->line );
return hist->line;
}
int
find_history( char *ptr, int min )
{
HIST *hist;
int len, num;
if ( *ptr=='!' )
return 1;
else if( *ptr=='-' )
return atoi(ptr+1);
else if (*ptr >= '0' && *ptr <= '9')
return H_len-(atoi(ptr)-H_tail_base)-1;
len = strlen(ptr);
for (hist=H_head,num=0; hist; hist=hist->next, num++)
if ( !strnicmp(hist->line, ptr, len) && num>=min)
return num;
return -1;
}
void
replace_head( char *str )
{
if (str && strlen(str) && H_head) {
free (H_head->line);
H_head->line = salloc (strlen(str)+1);
strcpy (H_head->line, str);
}
}
void
pError(char *str )
{
int ierr = (long)IoErr();
ierror(str, ierr);
}
ierror( char *str, int err )
{
PERROR *per = Perror;
char msgbuf[256];
setioerror(err);
if (err) {
if(err<500 && Fault(err,str,msgbuf,255)) {
fprintf(stderr,"%s\n",msgbuf);
return err;
}
else {
for (; per->errstr; ++per) {
if (per->errnum == err) {
fprintf (stderr, "%s%s%s\n",
per->errstr,
(str) ? ": " : "",
(str) ? str : "");
return err;
}
}
}
fprintf (stderr, "Unknown DOS error %d: %s\n", err, (str) ? str : "");
}
return err;
}
void
setioerror( int err )
{
static int LastIoError = -1;
char buf[20];
IoError=err;
if( IoError<0 ) IoError=0;
if( LastIoError!=IoError) {
LastIoError=IoError;
sprintf(buf, "%d", IoError);
set_var(LEVEL_SET, v_ioerr, buf);
}
}
char *
ioerror(int num)
{
PERROR *per = Perror;
for ( ; per->errstr; ++per)
if (per->errnum == num)
return per->errstr;
return NULL;
}
/*
* Disk directory routines
*
* dptr = dopen(name, stat)
* DPTR *dptr;
* char *name;
* int *stat;
*
* dnext(dptr, name, stat)
* DPTR *dptr;
* char **name;
* int *stat;
*
* dclose(dptr) -may be called with NULL without harm
*
* dopen() returns a struct DPTR, or NULL if the given file does not
* exist. stat will be set to 1 if the file is a directory. If the
* name is "", then the current directory is openned.
*
* dnext() returns 1 until there are no more entries. The **name and
* *stat are set. *stat != 0 if the file is a directory.
*
* dclose() closes a directory channel.
*
*/
DPTR *
dopen( char *name, int *stat)
{
DPTR *dp;
IoError=0;
*stat = 0;
dp = (DPTR *)salloc(sizeof(DPTR));
if (*name == '\0')
dp->lock = DupLock(Myprocess->pr_CurrentDir);
else
dp->lock = Lock (name,ACCESS_READ);
if (dp->lock == NULL) {
IoError=IoErr();
free (dp);
return NULL;
}
dp->fib = (FIB *)SAllocMem((long)sizeof(FIB), MEMF_PUBLIC);
if (!Examine (dp->lock, dp->fib)) {
pError (name);
dclose (dp);
return NULL;
}
if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
#ifdef MA_AMK
{
char *c;
if (c=strchr(name,':')) {
if (dp->dname = strdup(name))
dp->dvp = GetDeviceProc(dp->dname,NULL);
else
dp->dvp = NULL;
}
else {
dp->dname = NULL;
dp->dvp = NULL;
}
}
#endif
return dp;
}
static int
dnext( DPTR *dp, char **pname, int *stat)
{
if (dp == NULL) return (0);
if (ExNext (dp->lock, dp->fib)) {
*stat = 0;
if( dp->fib->fib_DirEntryType >= 0)
*stat= dp->fib->fib_DirEntryType!=ST_USERDIR ? 2 : 1;
*pname = dp->fib->fib_FileName;
return 1;
}
#ifdef MA_AMK
{
BOOL ma_done = FALSE;
if (IoErr()==ERROR_NO_MORE_ENTRIES) {
while (!ma_done && dp->dvp && (dp->dvp->dvp_Flags&DVPF_ASSIGN)) {
dp->dvp = GetDeviceProc(dp->dname,dp->dvp);
if (dp->dvp && dp->dvp->dvp_Lock) {
char buf[256];
BPTR new_lock,old_lock;
char *add = strchr(dp->dname,':')+1;
if (NameFromLock(dp->dvp->dvp_Lock,buf,255)) {
AddPart(buf,add,255);
printf("½%s╗\n",buf);
if (new_lock=Lock(buf,ACCESS_READ)) {
if (Examine(new_lock,dp->fib)) {
if (dp->lock) UnLock(dp->lock);
dp->lock = new_lock;
if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
*pname = dp->fib->fib_FileName;
return 1;
ma_done = TRUE;
}
}
}
else {
fprintf(stderr,"csh.dnext: NameFromLock() failed\n");
}
}
}
}
}
#endif
return 0;
}
int
dclose( DPTR *dp )
{
if (dp == NULL)
return 1;
if (dp->fib)
FreeMem (dp->fib,(long)sizeof(*dp->fib));
if (dp->lock)
UnLock (dp->lock);
#ifdef MA_AMK
if (dp->dvp)
FreeDeviceProc(dp->dvp);
#endif
free (dp);
return 1;
}
int
isdir( char *file )
{
DPTR *dp;
int stat;
stat = 0;
if (dp = dopen (file, &stat))
dclose(dp);
return (stat!=0);
}
void
free_expand( char **av )
{
char **get = av;
if (av) {
while (*get)
free (*get++-sizeof(FILEINFO));
free (av);
}
}
/*
* EXPAND(base,pac)
* base - char * (example: "df0:*.c")
* pac - int * will be set to # of arguments.
*
* 22-May-87 SJD. Heavily modified to allow recursive wild carding and
* simple directory/file lookups. Returns a pointer to
* an array of pointers that contains the full file spec
* eg. 'df0:c/sear*' would result in : 'df0:C/Search'
*
* Now no longer necessary to Examine the files a second time
* in do_dir since expand will return the full file info
* appended to the file name. Set by formatfile().
*
* Caller must call free_expand when done with the array.
*
* base bname = ename =
* ------ ------- -------
* "*" "" "*"
* "!*.info" "" "*.info" (wild_exclude set)
* "su*d/*" "" "*" (tail set)
* "file.*" "" "file.*"
* "df0:c/*" "df0:c" "*"
* "" "" "*"
* "df0:.../*" "df0:" "*" (recur set)
* "df0:sub/.../*" "df0:sub" "*" (recur set)
*
* ---the above base would be provided by execom.c or do_dir().
* ---the below base would only be called from do_dir().
*
* "file.c" "file.c" "" if (dp == 0) fail else get file.c
* "df0:" "df0:" "*"
* "file/file" "file/file" "" if (dp == 0) fail
* "df0:.../" "df0:" "*" (recur set)
*
*/
char **
expand( char *base, int *pac )
{
char *ptr;
char **eav = (char **)salloc(sizeof(char *) * (2));
short eleft, eac;
char *name;
char *bname, *ename, *tail;
int stat, recur, scr, bl;
DPTR *dp;
PATTERN *pat;
IoError = *pac = recur = eleft = eac = 0;
/* kprintf("Analyzing: %s\n",base); */
base = strcpy(salloc(strlen(base)+1), base);
#if 1
/*for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);*/
for (ptr = base; *ptr && *ptr != '?' && *ptr != '*' && *ptr != '[' && *ptr != ']'; ++ptr);
#else
/* AMK: experimental DOS pattern detection */
/*printf("trying to expand... %s\n",base);*/
for (ptr=base; *ptr && *ptr != '?' && *ptr!='*' && *ptr!='!' &&
*ptr != '(' && *ptr!=')' &&
*ptr != '|' && *ptr!='%' &&
*ptr != '~' && *ptr!='#' &&
*ptr != '[' && *ptr!=']';
++ptr);
#endif
if (!*ptr) /* no wild cards */
--ptr;
else
for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
if (ptr < base) {
bname = strcpy (salloc(1), "");
} else {
scr = ptr[1];
ptr[1] = '\0';
if (!strcmp(ptr-3,".../")) {
recur = 1;
*(ptr-3) = '\0';
}
bname = strcpy (salloc(strlen(base)+2), base);
ptr[1] = scr;
}
bl = strlen(bname);
ename = ++ptr;
for (; *ptr && *ptr != '/'; ++ptr);
scr = *ptr;
*ptr = '\0';
if (scr) ++ptr;
tail = ptr;
if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
free (bname);
free (base);
free (eav);
return NULL;
}
if (!stat) { /* eg. 'dir file' */
char *p,*s;
for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
if (*s=='/' || *s==':') s++;
*s=0;
eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
goto done;
}
if (!*ename) ename = "*"; /* eg. dir df0: */
if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
bname[bl] = '/';
bname[++bl] = '\0';
}
#if 0
if (stat) {
kprintf("isdir: %s, examining: %s\n",bname,ename);
}
#endif
pat= compare_preparse( ename, 0 );
while ((dnext (dp, &name, &stat)) && !breakcheck()) {
int match = compare_ok( pat, name);
if (match && (recur || !*tail)) {
if (eleft < 2) {
char **scrav = (char **)salloc(sizeof(char *) * (eac + 10));
memmove (scrav, eav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
eav[eac++] = svfile(bname,name,dp->fib);
--eleft;
}
if ((*tail && match) || recur) {
int alt_ac;
char *search, **alt_av, **scrav;
BPTR lock;
if (stat!=1) /* expect more dirs, but this not a dir */
continue;
lock = CurrentDir (dp->lock);
search = salloc(strlen(ename)+strlen(name)+strlen(tail)+6);
strcpy (search, name);
strcat (search, "/");
if (recur) {
strcat(search, ".../");
strcat(search, ename);
}
strcat (search, tail);
scrav = alt_av = expand (search, &alt_ac);
free(search);
CurrentDir (lock);
if (scrav) {
while (*scrav) {
int l;
if (eleft < 2) {
char **scrav = (char **)salloc(sizeof(char *)*(eac+10));
memmove ( scrav, eav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
l = strlen(*scrav);
eav[eac] = salloc(bl+l+1+sizeof(FILEINFO));
memcpy( eav[eac], *scrav-sizeof(FILEINFO),sizeof(FILEINFO));
eav[eac]+=sizeof(FILEINFO);
strcpy( eav[eac], bname);
strcat( eav[eac], *scrav);
free (*scrav-sizeof(FILEINFO));
++scrav;
--eleft, ++eac;
}
free (alt_av);
}
}
}
compare_free( pat );
done:
dclose (dp);
*pac = eac;
eav[eac] = NULL;
free (bname);
free (base);
if (eac) {
int i, j, len;
QuickSort( eav, eac );
for( i=0; i<eac-1; i++ ) {
len=strlen(eav[i]);
for( j=i+1; j<eac && !strnicmp(eav[i],eav[j],len); j++ )
if( !stricmp(eav[j]+len,".info")) {
((FILEINFO*)eav[i]-1)->flags |= INFO_INFO;
break;
}
}
return eav;
}
free (eav);
return NULL;
}
char *strdel(char *s,int from,int len)
{
while( s[from] ) {
s[from] = s[from+len];
++from;
}
return(s);
}
char *
strupr( char *s )
{
char *old=s;
while (*s) *s=toupper(*s), s++;
return old;
}
char *
strlwr( char *s )
{
char *old=s;
while (*s) *s=tolower(*s), s++;
return old;
}
/*
* Compare a wild card name with a normal name
*/
extern void *PatternBase;
PATTERN *
compare_preparse( char *wild, int casedep )
{
/* struct pattern *pat=salloc(256);*/
struct pattern *pat;
char *my_wild = wild;
pat = salloc(sizeof(struct pattern) + strlen(wild)*2 + 3);
/* this is not exact ('lil bit too much) but better readable */
pat->casedep=casedep;
if (pat->queryflag=(*wild=='&')) wild++;
my_wild = salloc(strlen(wild)+3);
strcpy(my_wild,wild);
if (*my_wild=='!') *my_wild='~';
if (!casedep) strlwr(my_wild);
if (*my_wild=='~') {
strins(my_wild+1,"(");
strcat(my_wild,")");
}
DOSBase->dl_Root->rn_Flags |= RNF_WILDSTAR;
if (PatternBase) {
if ((pat->patptr=AllocPattern( my_wild, 0 ))<0) {
free(pat);
free(my_wild);
return NULL;
}
}
else {
if ((ParsePattern(my_wild,pat->pattern,strlen(wild)*2+2)<0)) {
free(pat);
free(my_wild);
return NULL;
}
}
free(my_wild);
return pat;
}
int
compare_ok( PATTERN *pat, char *name )
{
char *lowname=name;
if (!pat)
return 0;
if (!pat->casedep) {
if (lowname=strdup(name))
strlwr(lowname);
else
return 0;
}
DOSBase->dl_Root->rn_Flags |= RNF_WILDSTAR;
if (PatternBase) {
if (MatchThePattern(pat->patptr,lowname)!=1) {
if (lowname!=name) free(lowname);
return 0;
}
} else {
if (!MatchPattern(pat->pattern,lowname)) {
if (lowname!=name) free(lowname);
return 0;
}
}
if (lowname!=name)
free(lowname);
if (pat->queryflag) {
char buf[260];
printf("Select %s%-16s%s [y/n] ? ",o_hilite,name,o_lolite);
gets(buf);
return (toupper(*buf)=='Y');
}
return 1;
}
void
compare_free( PATTERN *pat )
{
if( !pat )
return;
if( PatternBase )
FreePattern(pat->patptr);
free( pat );
}
#if 0
int
compare_strings( char *pattern, char *str, int casedep )
{
PATTERN *pat=compare_preparse( pattern, casedep );
int ret=compare_ok(pat,str);
compare_free(pat);
return ret;
}
#endif
static char *
svfile( char *s1, char *s2, FIB *fib)
{
FILEINFO *info=salloc(sizeof(FILEINFO)+strlen(s1)+strlen(s2)+1);
char *p = (char *)(info+1);
strcpy(p, s1);
strcat(p, s2);
info->flags = fib->fib_Protection | (*fib->fib_Comment ? INFO_COMMENT : 0);
info->type = fib->fib_DirEntryType;
info->size = (fib->fib_DirEntryType<0 || fib->fib_DirEntryType==ST_SOFTLINK) ? fib->fib_Size : -1;
info->blocks= (fib->fib_DirEntryType<0 || fib->fib_DirEntryType==ST_SOFTLINK) ? fib->fib_NumBlocks : 0;
info->date = fib->fib_Date;
info->uid = fib->fib_OwnerUID;
info->gid = fib->fib_OwnerGID;
info->class[0]=1;
return p;
}
static char *FullPath;
static FIB *PrevFile;
static int (*Action)(long, char *, char *);
static long Mask;
static int Queued=0;
static int
passinfo( FIB *fib )
{
char *p = (char *)(PrevFile+1);
int oldlen, ret=0;
if( Queued ) {
oldlen=strlen(FullPath);
/* AMK: don't know the exact length... used dummy 256L */
AddPart( FullPath, p, 256L );
ret=(*Action)( Mask, p, FullPath );
FullPath[oldlen]=0;
Queued=0;
}
if( fib ) {
*PrevFile= *fib;
strcpy( p, fib->fib_FileName);
Queued=1;
}
return ret;
}
static int
nu_recurse( char *name )
{
BPTR lock, cwd;
FIB *fib =(FIB *)SAllocMem(sizeof(FIB),MEMF_PUBLIC);
int oldlen=strlen( FullPath ), ret=0;
/* AMK: don't know the length... used dummy 256L */
AddPart( FullPath, name, 256L );
if (lock=Lock(name,ACCESS_READ)) {
if( Mask & SCAN_DIRENTRY )
(*Action)( SCAN_DIRENTRY, name, FullPath );
cwd =CurrentDir(lock);
if (Examine(lock, fib)) {
while (ExNext(lock, fib) && !breakcheck()) {
if (fib->fib_DirEntryType==ST_USERDIR) {
if ( Mask & SCAN_RECURSE ) {
if(!ret && !(ret=passinfo( NULL )))
ret=nu_recurse(fib->fib_FileName);
}
if ( Mask & SCAN_DIR )
if( !ret )
ret=passinfo( fib );
} else if( fib->fib_DirEntryType<0 && Mask & SCAN_FILE )
if( !ret )
ret=passinfo( fib );
}
if( breakcheck() )
ret=5;
if( !ret )
passinfo( NULL );
}
UnLock(CurrentDir(cwd));
if( Mask & SCAN_DIREND )
(*Action)( SCAN_DIREND, name, FullPath );
} else
pError(name);
FullPath[oldlen]=0;
FreeMem(fib, sizeof(FIB));
return ret;
}
int
newrecurse(int mask, char *name, int (*action)FUNCARG(long,char *,char *))
{
int ret;
FullPath = salloc( 512 );
PrevFile = salloc( sizeof(FIB)+108+1 );
Action = action;
Mask = mask;
Queued = 0;
*FullPath= 0;
ret=nu_recurse( name );
free( PrevFile );
free( FullPath );
return ret;
}
/* Sort routines */
static int reverse, factor;
int
cmp( FILEINFO *s1, FILEINFO *s2)
{
return stricmp( (char *)(s1+1), (char *)(s2+1) );
}
int
cmp_case( FILEINFO *s1, FILEINFO *s2)
{
return strcmp( (char *)(s1+1), (char *)(s2+1) );
}
int
sizecmp( FILEINFO *s1, FILEINFO *s2)
{
return s2->size - s1->size;
}
int
datecmp_csh( FILEINFO *s1, FILEINFO *s2 )
{
int r;
struct DateStamp *d1 = &s1->date, *d2 = &s2->date;
if( !(r= d2->ds_Days - d1->ds_Days))
if( !(r=d2->ds_Minute - d1->ds_Minute ) )
r=d2->ds_Tick - d1->ds_Tick;
return r;
}
int
numcmp( FILEINFO *s1, FILEINFO *s2 )
{
return atoi((char *)(s1+1))-atoi((char *)(s2+1));
}
static void
enterclass( FILEINFO *info )
{
char *class, *iclass=info->class, *t;
if( *iclass==1 ) {
if( class=getclass( (char *)(info+1))) {
strncpy( iclass, class, 11 );
iclass[11]=0;
if( t=index(iclass,0xA0))
*t=0;
} else
iclass[0]=0;
}
}
int
classcmp( FILEINFO *info1, FILEINFO *info2 )
{
int r;
enterclass( info1 );
enterclass( info2 );
r= stricmp( info1->class, info2->class );
if( !r ) r=stricmp((char *)(info1+1),(char *)(info2+1));
return r;
}
void
QuickSort( char *av[], int n)
{
reverse=factor=0;
DirQuickSort( av, n, cmp, 0, 0 );
}
static int (*compare)(FILEINFO *, FILEINFO *);
static int
docompare(char *s1,char *s2)
{
FILEINFO *i1=(FILEINFO *)s1-1, *i2=(FILEINFO *)s2-1;
int r=(*compare)( i1,i2 );
if( reverse ) r = -r;
if( factor ) r+= factor*((i2->size<0) - (i1->size<0));
return r;
}
#define QSORT
void
DirQuickSort( char *av[], int n, int (*func)(FILEINFO *,FILEINFO *), int rev, int fac)
{
reverse=rev; compare=func; factor=fac;
quicksort( av, n-1 );
}
static void
quicksort( char **av, int n )
{
char **i, **j, *x, *t;
if( n>0 ) {
i=av; j=av+n; x=av[ n>>1 ];
do {
while( docompare(*i,x)<0 ) i++;
while( docompare(x,*j)<0 ) --j;
if( i<=j )
{ t = *i; *i = *j; *j=t; i++; j--; }
} while( i<=j );
if( j-av < av+n-i ) {
quicksort( av, j-av );
quicksort( i , av+n-i);
} else {
quicksort( i , av+n-i);
quicksort( av, j-av );
}
}
}
int
filesize( char *name )
{
BPTR lock;
struct FileInfoBlock *fib;
int len=0;
if( lock = Lock (name,ACCESS_READ)) {
if( fib=(struct FileInfoBlock *)AllocMem(sizeof(*fib),MEMF_PUBLIC)) {
if (Examine (lock, fib))
len=fib->fib_Size;
FreeMem( fib, sizeof(*fib));
}
UnLock(lock);
}
return len;
}
#ifndef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#endif
char **
and( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
{
char **av=(char **)salloc(MIN(ac1,ac2)*sizeof(char *) ), *str;
int i, j, k=0;
for( i=0; i<ac1; i++ )
for( j=0, str=base ? (char*)FilePart(av1[i]) : av1[i]; j<ac2; j++ )
if( !stricmp(str, base ? (char*)FilePart(av2[j]) : av2[j]))
av[k++]=av1[i];
*ac=k;
return av;
}
char **
without( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
{
char **av=(char **)salloc(ac1*sizeof(char *) ), *str;
int i, j, k=0;
for( i=0; i<ac1; i++ ) {
for( j=0, str=base ? (char*)FilePart(av1[i]) : av1[i]; j<ac2; j++ )
if( !stricmp(str, base ? (char*)FilePart(av2[j]) : av2[j] ) )
break;
if( j==ac2 )
av[k++]=av1[i];
}
*ac=k;
return av;
}
char **
or( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
{
char **av=(char **)salloc((ac1+ac2)*sizeof(char *) ), *str;
int i, j, k=0;
for( i=0; i<ac1; i++ )
av[k++]=av1[i];
for( i=0; i<ac2; i++ ) {
for( j=0, str=base ? (char*)FilePart(av2[i]) : av2[i]; j<ac1; j++ )
if( !stricmp(str, base ? (char*)FilePart(av1[j]) : av1[j] ) )
break;
if( j==ac1 )
av[k++]=av2[i];
}
*ac=k;
return av;
}
void
clear_archive_bit( char *name )
{
DPTR *dp;
int stat;
if(dp = dopen(name,&stat) ) {
setProtection( name, dp->fib->fib_Protection&~FIBF_ARCHIVE);
dclose( dp );
}
}
char *
itoa( int i )
{
static char buf[20];
char *pos=buf+19;
int count=4, flag=0;
if( i<0 )
flag=1, i = -i;
do {
if( !--count )
count=3, *--pos=',';
*--pos= i%10+'0';
} while( i/=10 );
if( flag )
*--pos='-';
return pos;
}
char *
itok( int i )
{
#if 0
static char buf[16], which;
char *exp=" KMG", *ptr= buf+(which=8-which);
#endif
/* now three buffers instead of two as needed for do_info() */
static char buf[24], which;
char *exp=" kMG", *ptr= buf+(8*(which=(which+1)%3));
int res,m=1024;
/* AMK: don't cripple small numbers */
if (i<1000) {
sprintf(ptr,"%d",i);
return ptr;
}
/* AMK: allow four places for kilobytes */
if ((res=(i+512)/1024)<10000) {
sprintf(ptr,"%dk",res);
return ptr;
}
/* AMK: because of HD floppies with 1760K (not 2MB :-) */
do {
/* res=(i+512)/m; */
res=(i+(m/2))/m;
m*=1024;
++exp;
}
while (res>999);
if (res==0)
res=1;
sprintf(ptr,"%d%c",res,*exp);
return ptr;
}
char *
next_a0( char *str )
{
while( *str && (UBYTE)*str!=0xA0 && *str!='=' && *str!=',') str++;
if( *str )
return str+1;
return NULL;
}
static int
gethex( char *str, int l )
{
int i, val=0, n, c;
if( *str=='.' ) return l==2 ? 256 : 0;
for( i=0; i<l || !l; i++ ) {
c = *str++;
if ( c>='0' && c<='9' ) n=c-'0';
else if( c>='a' && c<='f' ) n=c-'a'+10;
else if( c>='A' && c<='F' ) n=c-'A'+10;
else break;;
val=16*val+n;
}
return (l && i!=l) ? -1 : val;
}
strwrdcmp( char *str, char *wrd )
{
PATTERN *pat;
int ret;
char *ind=index(wrd,0xA0);
if( ind ) *ind=0;
pat=compare_preparse( wrd,0 );
ret=compare_ok(pat,str);
compare_free( pat );
if( ind ) *ind=0xA0;
return !ret;
}
int
wrdlen( char *str )
{
char *old=str;
while( *str && (UBYTE)*str!=0xA0 ) str++;
return str-old;
}
char *
getclass(char *file)
{
CLASS *cl;
char *class, *str, *arg, *get, *buf;
int offs, byte, len, fail;
BPTR fh;
if( isdir(file) ) return "dir";
if( !(buf=calloc(1024,1))) return NULL;
if( !(fh=Open(file,MODE_OLDFILE))) return NULL;
len=Read( fh,buf,1023);
Close(fh);
for( cl=CRoot; cl; cl=cl->next ) {
class=cl->name;
if(!(str=next_a0(cl->name))) continue;
while( str ) {
if(!(arg=next_a0( str ))) goto nextclass;
switch( *str ) {
case 's':
if( (offs=strlen(file)-wrdlen(arg))<0 ) break;
if( !strwrdcmp(file+offs,arg)) goto found;
break;
case 'n':
if( !strwrdcmp(FilePart(file),arg) ) goto found;
break;
case 'd':
goto found;
case 'o':
offs=gethex(arg,0);
if( !(arg=index(arg,','))) goto nextclass;
if( offs>len-10 ) break;
for( get=buf+offs, ++arg; (byte=gethex(arg,2))>=0; arg+=2 )
if( (UBYTE)*get++!=byte && byte!=256 )
goto nexttry;
goto found;
case 'c':
if( !len )
break;
for( get=buf, fail=0; get<buf+len; get++ )
if( *get<9 || *get>13 && *get<32 || *get>127 )
fail++;
if( fail*8>len )
break;
goto found;
case 'i':
break;
case 'a':
goto nextclass;
default:
goto nextclass;
}
nexttry: str=next_a0(arg);
}
nextclass: ;
}
free(buf);
return NULL;
found:
free(buf);
return (char *)class;
}
char *
superclass( char *subclass )
{
CLASS *cl;
char *cur;
int len;
for( len=0; subclass[len] && (UBYTE)subclass[len]!=0xA0; len++ ) ;
for( cl=CRoot; cl; cl=cl->next ) {
if( strncmp( cur=cl->name,subclass,len ))
continue;
do
cur=index( cur,0xA0 );
while( cur && *++cur!='i');
if( cur && (cur=index(cur,'=')))
return ++cur;
}
return NULL;
}
char *
getaction( char *class, char *action )
{
CLASS *cl;
char *cur, *ind;
int len;
for( len=0; class[len] && (UBYTE)class[len]!=0xA0; len++ ) ;
for( cl=CRoot; cl; cl=cl->next ) {
if( strncmp( cur=cl->name,class,len ) || !issep(cur[len]))
continue;
do
cur=index( cur,0xA0 );
while( cur && *++cur!='a');
if( cur && (cur=index( ++cur,0xA0 ))) {
do {
if( !(ind=index( ++cur,'=' )))
return NULL;
len=ind-cur;
if( len==strlen(action) && !strncmp(action,cur,len))
return ++ind;
} while( cur=index(cur,0xA0) );
}
}
return NULL;
}
int
doaction( char *file, char *action, char *args )
{
char *class, *com, *c, *copy;
int ret, spc=hasspace(file), i=0;
if( !(class=getclass(file)))
return exists(file) ? 10 : 9;
do
if( com=getaction(class,action))
break;
while( (class=superclass( class )) && ++i<4 );
if( !class )
return 11;
if( c=index(com,0xA0) )
*c=0;
copy=salloc( strlen(com)+strlen(file)+strlen(args)+7 );
sprintf(copy,spc?"%s \"%s\" %s":"%s %s %s", com, file, args);
ret=execute(copy);
free(copy);
if( c )
*c=0xA0;
return ret ? 12 : 0;
}
void *
salloc( int len )
{
void *ret;
if( !len ) len++;
if( !(ret=malloc(len))) {
fprintf(stderr,"Out of memory -- exiting\n");
main_exit( 20 );
}
return ret;
}
void *
SAllocMem( long size, long req )
{
void *ret;
if( !(ret=AllocMem(size,req))) {
fprintf(stderr,"Out of memory -- exiting\n");
main_exit( 20 );
}
return ret;
}
int
issep( char s )
{
return !s || ISSPACE(s) || s=='/' || s==';' || s=='|' || s=='&';
}
char *
filemap( char *buf, int last )
{
char *s=buf, *d, *lcd;
int len;
if( last && *s=='~' && issep(s[1])) {
if (!(lcd=get_var(LEVEL_SET,v_lcd)))
return buf;
len= strlen(lcd);
memmove( s+len, s+1, strlen(s)+1);
memcpy( s, lcd, strlen(lcd));
if( s[len]!='/' )
return buf;
s+=len+1;
}
d=s;
for( ;; ) {
if( s[0]=='.' && issep(s[1]) ) {
#if 0
char AmkBuf[256];
strcpy(AmkBuf,get_var(LEVEL_SET, v_cwd));
AddPart(AmkBuf,(s[1]==0)?s+1:s+2,255);
printf(". = %s\n",AmkBuf);
#endif
s+=1+(s[1]!=0);
}
else if( s[0]=='.' && s[1]=='.' && issep(s[2]))
*d++='/', s+=2+(s[2]!=0);
else
break;
}
while( *d++ = *s++ ) ;
return buf;
}
char *
safegets( char *buf, FILE *in )
{
char *t;
if( dobreak() )
return NULL;
if( !fgets(buf,249,in) )
return NULL;
if( t=index(buf,'\n' ))
*t=0;
return buf;
}
/* ------------------------ string array handling -------------------------- */
/*
* First call: pass "*array=NULL" and "*len=0" !!
*/
#define AL_BLOCKSIZE 20
BOOL add_array_list(char ***array, long *len, char *str)
{
char **new_array = *array;
long i = *len;
BOOL success=FALSE;
if (i%AL_BLOCKSIZE == 0) {
if (new_array = malloc((i+AL_BLOCKSIZE) * sizeof(char *))) {
memcpy(new_array,*array,i * sizeof(char *));
free(*array); /* free old array */
*array = new_array; /* set new array */
}
else
return(success);
}
if (new_array[i] = strdup(str)) {
*len = ++i; /* update length */
success = TRUE;
}
return(success);
}
void free_array_list(char **array, long len)
{
long i;
if (len>0) {
for (i=0; i<len; i++)
free(array[i]);
free(array);
}
}
/* ------------------------ string array handling -------------------------- */
#ifndef ACTION_SET_OWNER
#define ACTION_SET_OWNER 1036
#endif
BOOL SetOwner37(UBYTE *name, LONG uidgid)
{
struct DevProc *devproc = NULL;
BPTR lock;
char null[] = "\0\0\0\0"; /* longword aligned null-byte */
BOOL Res = FALSE;
while(devproc = GetDeviceProc(name, devproc))
{
if (lock = Lock(name, SHARED_LOCK))
{
Res = DoPkt(devproc->dvp_Port,
ACTION_SET_OWNER,
NULL, lock, MKBADDR(null+3), uidgid, NULL);
UnLock(lock);
break;
}
else if (IoErr() != ERROR_OBJECT_NOT_FOUND)
break;
}
if (devproc)
FreeDeviceProc(devproc);
else
if (IoErr() == ERROR_NO_MORE_ENTRIES)
SetIoErr(ERROR_OBJECT_NOT_FOUND);
return Res;
}
long setProtection( char *name, long mask )
{
long rc;
#ifdef MULTIUSER_SUPPORT
if (muBase)
rc = (long)muSetProtection( name, mask );
else
rc = (long)SetProtection( name, mask );
#else
rc = (long)SetProtection( name, mask );
#endif
return(rc);
}